#ifndef VECTOR2TEM_H
#define VECTOR2TEM_H

#include "imMaths.h"

#define SIZE 2

template <typename Real>
struct Vector2Tem {
public:
	union {
		struct {
			Real x, y;
		};
		Real Data[SIZE];
	};

	// Constructors
	Vector2Tem(void) {
		memset(&Data, 0, sizeof(Real) * SIZE);
	}
	Vector2Tem(const Real * f) {
		x = f[0];
		y = f[1];
	}
	Vector2Tem(Real _x, Real _y) {
		x = _x;
		y = _y;
	}

	// Members
	Vector2Tem<Real> ComponentProduct(const Vector2Tem<Real> &a) { // Multiply each component of the vector together
		return Vector2Tem<Real>(x * a.x,
							 y * a.y);
	}
	Real LengthSqr(void) { // Returns length^2 of vector. Note that this is faster than Length()
		return x*x + y*y;
	}
	Real Length(void) { // Returns length of vector
		return sqrt(LengthSqr());
	}
	void Normalize(void) { // Converts vector to unit length
		Real l = Length();
		x /= l;
		y /= l;
	}
	void AddScaledVector(const Vector2Tem<Real> &a, const Real &s) {
		x += a.x * s;
		y += a.y * s;
	}
	
	// Operators! Woo!
	Vector2Tem<Real> operator+(const Vector2Tem<Real> &a) {
		return Vector2Tem<Real> (x + a.x, y + a.y);
	}
	Vector2Tem<Real> operator-(const Vector2Tem<Real> &a) {
		return Vector2Tem<Real> (x - a.x, y - a.y);
	}
	Vector2Tem<Real> & operator+=(const Vector2Tem<Real> &a) {
		x += a.x;
		y += a.y;
		return *this;
	}
	Vector2Tem<Real> & operator-=(const Vector2Tem<Real> &a) {
		x -= a.x;
		y -= a.y;
		return *this;
	}
		
	Vector2Tem<Real> operator*(const Real &a) {
		return Vector2Tem<Real> (x * a, y * a);
	}
	Vector2Tem<Real> operator/(const Real &a) {
		return Vector2Tem<Real> (x / a, y / a);
	}
	Vector2Tem<Real> & operator*=(const Real &a) {
		x *= a;
		y *= a;
		return *this;
	}
	Vector2Tem<Real> & operator/=(const Real &a) {
		x /= a;
		y /= a;
		return *this;
	}

	bool operator== (const Vector2Tem<Real> &v) {
		Vector2Tem<Real> p = this->operator-(v);
		return abs(p.x) < FLT_EPSILON && abs(p.y) < FLT_EPSILON;
	}

	operator const Vector2Tem<float>(void) {
		Vector2Tem<float> o;

		for(int i = 0; i < SIZE; i++)
			o.Data[i] = (float)Data[i];

		return o;
	}

	operator const Vector2Tem<double>(void) {
		Vector2Tem<double> o;

		for(int i = 0; i < SIZE; i++)
			o.Data[i] = (double)Data[i];

		return o;
	}
};

#undef SIZE

typedef Vector2Tem<float> Vector2;
typedef Vector2Tem<float> Vector2f;
typedef Vector2Tem<double> Vector2d;

#endif